package com.google.appengine.codelab;

import static com.google.appengine.api.datastore.FetchOptions.Builder.withLimit;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.CompositeFilterOperator;
import com.google.appengine.api.datastore.Query.Filter;
import com.google.appengine.api.datastore.Query.FilterOperator;
import com.google.appengine.api.datastore.Query.FilterPredicate;

@SuppressWarnings("serial")
public class UserStory11Servlet extends BaseServlet {
		
		public void doGet(HttpServletRequest req, HttpServletResponse resp)
				throws ServletException, IOException {
			super.doGet(req, resp);
			insertEntities();
			PrintWriter out = resp.getWriter();
			if (req.getParameter("q").equals("q1")) {
				out.println(SearchByNav());		
			} 
		    return;
		}

	public static long countFraudesByNavegador(String nav_nome,
			String nav_versao) {
		DatastoreService ds = Util.getDatastoreServiceInstance();
		List<Filter> filter = new ArrayList<Filter>();
		long count = 0;
		Query query = new Query("Navegador");
		if (nav_nome != "") {
			filter.add(new FilterPredicate("nav_nome", FilterOperator.EQUAL,
					nav_nome));
		}
		if (nav_versao != "") {
			filter.add(new FilterPredicate("nav_versao", FilterOperator.EQUAL,
					nav_versao));
		}
		if (filter.size() > 0) {
			query.setFilter(filter.size() == 1 ? filter.get(0)
					: CompositeFilterOperator.and(filter));
		}
		for (Entity sis : ds.prepare(query).asIterable()) {
			for (Entity ses : new Sessao().getByNavId(sis.getKey().getId())
					.asIterable()) {
				for (Entity tra : getTransacaoBySesId(ses.getKey().getId())
						.asIterable()) {
					count += getFraudeByTransId(tra.getKey().getName())
							.countEntities(withLimit(10000));
				}
			}
		}
		return count;
	}

	public static PreparedQuery getByFilter(String kind, Filter filter) {
		DatastoreService ds = Util.getDatastoreServiceInstance();
		Query query = new Query(kind);
		query.setFilter(filter);
		return ds.prepare(query);
	}

	public static PreparedQuery getFraudeByTransId(String trans_id) {
		Filter filter = new FilterPredicate("trans_id", FilterOperator.EQUAL,
				trans_id);
		return getByFilter("Fraude", filter);
	}

	public static PreparedQuery getTransacaoBySesId(long ses_id) {
		Filter filter = new FilterPredicate("ses_id", FilterOperator.EQUAL,
				ses_id);
		return getByFilter("Transacao", filter);
	}

	public static String SearchByNav() {
		long total = countFraudesByNavegador("", "");
		StringBuilder sb = new StringBuilder();
		sb.append("{\"data\": [");
		for (Entity sis : new Navegador().getAll().asIterable()) {
			String nav_nome = sis.getProperty("nav_nome").toString();
			String nav_versao = sis.getProperty("nav_versao").toString();
			
			long count = countFraudesByNavegador(nav_nome, nav_versao);
			sb.append("{\"name\":");
			sb.append("\"" + nav_nome + "\"");
			sb.append(",\"version\":");
			sb.append("\"" + nav_versao + "\"");
			sb.append(",\"count\":");
			sb.append("\"" + count + "\"");
			sb.append(",\"percentage\":");
			sb.append("\"" + String.format("%.2f%%", new Float((count * 100) / (double) total))
					+ "\"");
			sb.append("},");
		}
		sb.deleteCharAt(sb.lastIndexOf(","));
		sb.append("]}");
		return sb.toString();
	}
	
	
	private void insertEntities() {
		Localidade.createOrUpdateLocalidade("1", new Float(-13.58), new Float(-51.85), "", "", "", "", "");
		Localidade.createOrUpdateLocalidade("2", new Float(-15.78), new Float(-47.92), "", "", "", "", "");
		
		Cliente.createOrUpdateCliente("1", "joao", "Joao", "Costa", "", "", "", "1");
		Cliente.createOrUpdateCliente("2", "jose", "JOSE", "SILVA", "", "", "", "1");
		Cliente.createOrUpdateCliente("3", "maria", "MARIA", "BENEDITA", "", "", "", "1");
		
		Estabelecimento.createOrUpdateEstabelecimento("1", "", "ESTABELECIMENTO1", "1");
		Estabelecimento.createOrUpdateEstabelecimento("2", "", "ESTABELECIMENTO2", "2");
		
		Midia.createOrUpdateMidia("1", "MIDIA", "", "", "", "1");
		Midia.createOrUpdateMidia("2", "MIDIA", "", "", "", "2");
		Midia.createOrUpdateMidia("3", "MIDIA", "", "", "", "3");
		
		Transacao.createOrUpdateTransacao("1", "", new Double(10), "20130602", "", "1", "1", "1", "1");
		Transacao.createOrUpdateTransacao("2", "", new Double(10), "20130602", "", "1", "2", "2", "1");
		Transacao.createOrUpdateTransacao("3", "", new Double(500.1), "20130602", "", "1", "2", "2", "1");
		Transacao.createOrUpdateTransacao("4", "", new Double(25), "20130602", "", "1", "2", "2", "1");
		Transacao.createOrUpdateTransacao("5", "", new Double(80), "20130602", "", "1", "3", "3", "1");
		Transacao.createOrUpdateTransacao("6", "", new Double(500), "20130602", "", "1", "3", "3", "2");
		Transacao.createOrUpdateTransacao("7", "", new Double(50), "20130602", "", "1", "3", "3", "2");
		Transacao.createOrUpdateTransacao("8", "", new Double(50), "20130602", "", "1", "3", "3", "2");
		Transacao.createOrUpdateTransacao("9", "", new Double(30), "20130602", "", "1", "3", "3", "2");
		Transacao.createOrUpdateTransacao("10", "", new Double(100), "20130602", "", "1", "2", "3", "2");
		Transacao.createOrUpdateTransacao("11", "", new Double(15), "20130602", "", "1", "2", "3", "2");
		Transacao.createOrUpdateTransacao("12", "", new Double(120), "20130602", "", "1", "1", "3", "2");
		
		Fraude.createOrUpdateFraude("1", "FRAUDE1", "TIPO1", "", "09/06/2013", "2");
		Fraude.createOrUpdateFraude("2", "FRAUDE2", "TIPO1", "", "09/06/2013", "3");
		Fraude.createOrUpdateFraude("3", "FRAUDE3", "TIPO1", "", "09/06/2013", "6");
		Fraude.createOrUpdateFraude("4", "FRAUDE4", "TIPO1", "", "09/06/2013", "7");
		Fraude.createOrUpdateFraude("5", "FRAUDE5", "TIPO1", "", "09/06/2013", "10");
		Fraude.createOrUpdateFraude("6", "FRAUDE6", "TIPO1", "", "09/06/2013", "12");
		
		SistemaOperacional sis = new SistemaOperacional();
		sis.createOrUpdate(1, "Windows XP", "5.1", "0");
		sis.createOrUpdate(2, "Windows 7", "6.1", "0");
		sis.createOrUpdate(3, "Ubuntu", "12.04", "0");
		sis.createOrUpdate(4, "Android", "4.1", "1");
		sis.createOrUpdate(5, "Android", "4.2", "1");
		sis.createOrUpdate(6, "iOS", "6.0", "1");
		
		Navegador nav = new Navegador();
		nav.createOrUpdate(1, "Chrome", "27.0");
		nav.createOrUpdate(2, "Firefox", "21.0");
		nav.createOrUpdate(3, "Internet Explorer", "9.0");
		
		Sessao ses = new Sessao();
		ses.createOrUpdate(1, "1", 3, 1, "20130606", "19:30:00");
		ses.createOrUpdate(2, "2", 1, 2, "20130606", "19:31:00");
		ses.createOrUpdate(3, "3", 5, 1, "20130606", "19:32:00");
		ses.createOrUpdate(4, "3", 2, 3, "20130606", "19:35:00");
		ses.createOrUpdate(5, "1", 4, 1, "20130609", "08:31:00");
		
		Transacao.updateSessao("2", 2);
		Transacao.updateSessao("3", 4);
		Transacao.updateSessao("10", 2);
		Transacao.updateSessao("12", 5);
	}



}
